#!/usr/bin/env python
# coding: utf-8

# ### 日期
# 更新日期：10.31（更新内容） 11.01（更新内容） 11.14（更新内容）11.17（更新内容） 撰写人：吕泓鹭

# ## 课堂学习内容：
# 
# > * 1、高德api-web服务
# > * 2、API经济成本的预估（调用量、并发量）
# > * 3、地理编码
# ...
# ## 课后练习:
# > * 1.[地理编码/逆地理编码](https://lbs.amap.com/api/webservice/guide/api/georegeo)
# > * 2.[路径规划](https://lbs.amap.com/api/webservice/guide/api/direction)
# > * 3.[行政区域查询](https://lbs.amap.com/api/webservice/guide/api/district)
# > * 4.[POI搜索](https://lbs.amap.com/api/webservice/guide/api/search)
# > * 5.[ip定位](https://lbs.amap.com/api/webservice/guide/api/ipconfig)
# > * 6.[静态地图](https://lbs.amap.com/api/webservice/guide/api/staticmaps)
# > * 7.[坐标转换](https://lbs.amap.com/api/webservice/guide/api/convert)
# > * 8.[天气查询](https://lbs.amap.com/api/webservice/guide/api/weatherinfo)
# > * 9.[输入提示](https://lbs.amap.com/api/webservice/guide/api/inputtips)

# ### 准备工作

# In[1]:


import requests,json
import pandas as pd
from PIL import Image
from io import BytesIO
lv_key = '080f4a518f90c6635b42d91498de767e' # 到高德官网注册账号申请web服务API类型key


# ### 地理编码
# 
# > * 1、结构化地址的定义： 首先，地址肯定是一串字符，内含国家、省份、城市、区县、城镇、乡村、街道、门牌号码、屋邨、大厦等建筑物名称。按照由大区域名称到小区域名称组合在一起的字符。一个有效的地址应该是独一无二的。注意：针对大陆、港、澳地区的地理编码转换时可以将国家信息选择性的忽略，但省、市、城镇等级别的地址构成是不能忽略的。暂时不支持返回台湾省的详细地址信息。
# > * 2、URL：https://restapi.amap.com/v3/geocode/geo?parameters
# > * 3、request.get()
# > * 4、参数：
# >> * A.必选参数：key（高德API密钥），address（结构化地址）
# >> * B.可选参数：
# >>> * city（可选输入内容包括：指定城市的中文（如北京）、指定城市的中文全拼（beijing）、citycode（010）、adcode（110000），不支持县级市。当指定城市查询内容为空时，会进行全国范围内的地址转换检索。）
# >>> * batch（batch 参数设置为 true 时进行批量查询操作，最多支持 10 个地址进行批量查询；batch 参数设置为 false 时进行单点查询。）
# >>> * output（设置 JSON 返回结果数据将会以JSON结构构成；如果设置 XML 返回结果数据将以 XML 结构构成。）
# >>> * callback（callback 值是用户定义的函数名称，此参数只在 output 参数设置为 JSON 时有效，缺省值：无。）
# > * 5. 具体应用场景：为用户返回指定地点的坐标，为后续搜索提供前提数据。

# <font size=5px>先用传统方法调用，后用函数调用</font>

# In[3]:


#### 准备数据 
中大南方_address = "广东省广州市中山大学南方学院"


# In[4]:


url = "https://restapi.amap.com/v3/geocode/geo?parameters"
params = {
    "key":lv_key,
    "address":中大南方_address,
    "output":"json"
}
# positional argument follows keyword argument
# pa 一定要放在前面，keyword argument放在末尾！！！可以
response = requests.get(url,params=params)
response


# In[5]:


response.json()


# In[6]:


中大南方_location = response.json()['geocodes'][0]['location']
中大南方_location


# <font size=5px>尝试以函数的形式来做高德api</font>

# In[7]:


def geocode(key,address,city,batch='false',output='JSON',callback=None):
    # 自定义函数名称为“geocode”，括号内为参数。
    url = "https://restapi.amap.com/v3/geocode/geo?parameters"
    params = {
        "key":key,
        "address":address,
        "city":city,
        "batch":batch,
        "output":output,
        "callback":callback
    }
    response = requests.get(url,params=params)
    results = response.json()['geocodes'][0]['location']  # 列表提取
    return results  # 返回值


# In[10]:


address_1 = '广东省广州市中山大学南方学院'
city_1 = "广东"


# In[11]:


geocode(lv_key,address_1,city_1)


# ### 逆地理编码
# 
# > * 1.逆地理编码可以将经纬度转换为详细结构化的地址，且返回附近周边的POI、AOI信息。
# > * 2.url:https://restapi.amap.com/v3/geocode/regeo?parameters （官网有提供）
# > * 3.requests.get()
# > * 4.参数：
# >> * 4.1必选参数：key、location(经纬度坐标)
# >> * 4.2可选参数：
# >>> * poitype(返回附近POI类型,需要extensions参数为all时才生效,参数仅支持传入POI TYPECODE，可以传入多个POI TYPECODE，相互之间用“|”分隔。该参数在 batch 取值为true时不生效。获取 POI TYPECODE 可以参考[POI分类码表](https://lbs.amap.com/api/webservice/download)
# >>> * radius（搜索半径，取值范围在0~3000，默认是1000。单位：米，缺省值：1000）
# >>> * extensions(默认取值是 base，也就是返回基本地址信息；值为 all 时会返回基本地址信息、附近 POI 内容、道路信息以及道路交叉口信息。)
# >>> * batch(参数设置为 true 时进行批量查询操作，最多支持 20 个经纬度点进行批量地址查询操作。设置为 false 时进行单点查询，此时即使传入多个经纬度也只返回第一个经纬度的地址解析查询结果。)
# >>> * roadlevel（道路等级。当roadlevel=0时，显示所有道路，当roadlevel=1时，过滤非主干道路，仅输出主干道路数据。需要 extensions 参数为 all 时才生效）
# >>> * output
# >>> * callback
# >>> * homeorcorp（供三个可选参数：0：不对召回的排序策略进行干扰。1：综合大数据分析将居家相关的 POI 内容优先返回，即优化返回结果中 pois 字段的poi顺序。2：综合大数据分析将公司相关的 POI 内容优先返回，即优化返回结果中 pois 字段的poi顺序。需要 extensions 参数为 all 时才生效）
# > * 5.具体应用场景：提供给用户搜索当前所在地周边的生活基础设施，了解当前所在地的繁荣度。

# In[12]:


# 数据准备 中大南方_location


# In[13]:


# 逆地理编码函数
def regeo(key,location,poitype=None,radius=1000,extensions='all',batch='false',output='JSON',callback=None,roadlevel=1,homeorcorp=0):
    url = "https://restapi.amap.com/v3/geocode/regeo?parameters"
    params = {
        "key":key,
        "location":location,
        "poitype":poitype,
        "radius":radius,
        "extensions":extensions,
        "batch":batch,
        "output":output,
        "callback":callback,
        "roadlevel":roadlevel,
        "homeorcorp":homeorcorp
    }
    response = requests.get(url=url,params=params)
    results = pd.json_normalize(response.json()['regeocode']['pois'])
    return results  # 返回值


# In[14]:


中大南方_location = geocode(lv_key,address_1,city_1)


# In[15]:


regeo(lv_key,中大南方_location)


# ### 路径规划
# > * 1.规划通勤方案，并且返回通勤方案的数据。
# > * 2.url
# >> * 2.1步行url:https://restapi.amap.com/v3/direction/walking?parameters
# >> * 2.2公交：https://restapi.amap.com/v3/direction/transit/integrated?parameters
# >> * 2.3驾车：https://restapi.amap.com/v3/direction/driving?parameters
# > * 3。具体应用场景：帮助用户规划通勤方案。

# In[16]:


# 数据准备(出发地、目的地)
origin_中大南方 = geocode(lv_key,address_1,city_1)
destination_暨南大学_1 = "广东省广州市暨南大学"
destination_暨南大学 = geocode(lv_key,destination_暨南大学_1,city_1)


# #### 步行
# 
# > * 1、url:https://restapi.amap.com/v3/direction/walking?parameters
# > * 2、requests.get()
# > * 3、参数：
# 
# >> * A.必选：key,origin(出发点（经度，纬度）)，destination（目的地（经度，纬度））
# >> * B.可选：

# In[18]:


"""获取步行路径函数"""
"""origin为起始地的坐标，destination为目的地的坐标"""
def walking(key,origin,destination,output='JSON',callback=None):
    url = "https://restapi.amap.com/v3/direction/walking?parameters"
    params = {
        "key":key,
        "origin":origin,
        "destination":destination,
        "output":output,
        "callback":callback
    }
    response = requests.get(url=url,params=params)
    result = pd.json_normalize(response.json()['route']['paths'][0]['steps'])
    return result


# In[19]:


walking(lv_key,origin_中大南方,destination_暨南大学)


# #### 公交车
# 
# 1.公交URL：https://restapi.amap.com/v3/direction/transit/integrated?parameters    
# 2.请求方式：request.get   
# 3.必填参数：key、origin（出发地坐标）、destination（目的地坐标）、city（出发地城市）、cityd（目的地城市：同城可不填，跨城必填）

# In[21]:


"""获取公交路径的函数"""
"""origin为起始地的坐标，destination为目的地的坐标,city为出发地城市，cityd为目的地城市"""
def bus(key,origin,destination,city,cityd,extensions='base',strategy=3,nightflag=0,output='JSON',callback=None):
    url = "https://restapi.amap.com/v3/direction/transit/integrated?parameters"
    params = {
        "key":key,
        "origin":origin,
        "destination":destination,
        "city":city,
        "cityd":cityd,
        "extensions":extensions,
        "strategy":strategy,
        "nightflag":nightflag,
        "output":output,
        "callback":callback
    }
    response = requests.get(url,params=params)
    results = response.json()
    return results


# In[22]:


bus(lv_key,origin_中大南方,destination_暨南大学,'广东','广东')


# In[23]:


# 步行前往车站路径
pd.json_normalize(bus(lv_key,origin_中大南方,destination_暨南大学,'广东','广东')['route']['transits'][0]['segments'][0]['walking']['steps'])


# In[24]:


# 需要乘坐的公交车信息
pd.json_normalize(bus(lv_key,origin_中大南方,destination_暨南大学,'广东','广东')['route']['transits'][0]['segments'][0]['bus']['buslines'][0])


# In[25]:


# 公交车途径站点
pd.json_normalize(bus(lv_key,origin_中大南方,destination_暨南大学,'广东','广东')['route']['transits'][0]['segments'][0]['bus']['buslines'][0]['via_stops'])


# #### 驾车路径

# In[26]:


"""获取驾车路径函数"""
"""origin为起始地的坐标，destination为目的地的坐标"""
"""province为车牌省份汉字缩写，number为车牌处省份外的字母与数字"""
def driving(key,origin,destination,province,number,cartype=0,strategy=10,originid=None,destinationid=None,origintype=None,destinationtype=None,waypoints=None,avoidpolygons=None,avoidroad=None,ferry=0,roadaggregation='false',nosteps=0,output='JSON',callback=None,extensions='base'):
    # 自定义函数名称为driving，括号内为参数。
    url = "https://restapi.amap.com/v3/direction/driving?parameters"
    params = {
        "key":key,
        "origin":origin,
        "destination":destination,
        "originid":originid,
        "destinationid":destinationid,
        "origintype":origintype,
        "destinationtype":destinationtype,
        "strategy":strategy,
        "waypoints":waypoints,
        "avoidpolygons":avoidpolygons,
        "province":province,
        "number":number,
        "cartype":cartype,
        "ferry":ferry,
        "roadaggregation":roadaggregation,
        "nosteps":nosteps,
        "output":output,
        "callback":callback,
        "extensions":extensions
    }
    response = requests.get(url,params=params)
    # 使用normalize函数制作成表格，并提取处我们想要的信息，方便阅读。
    results = pd.json_normalize(response.json()['route']['paths'][0]['steps'])
    return results


# In[27]:


driving_origin = origin_中大南方
driving_destination = destination_暨南大学
driving_province = "粤"
driving_number = "4778"


# In[28]:


driving(lv_key,driving_origin,driving_destination,driving_province,driving_number)


# ### 行政区域查询
# > * 1.行政区域查询是一类简单的HTTP接口，根据用户输入的搜索条件可以帮助用户快速的查找特定的行政区域信。
# > * 2.url:https://restapi.amap.com/v3/config/district?parameters
# > * 3.参数：
# >> * 3.1必选参数：key
# > * 4. 具体应用场景：帮助用户查询行政区域
# 

# In[29]:


"""查询行政区域函数"""
"""keywords为省市名称"""
def administration(key,keywords,subdistrict=1,page=1,offset=20,extensions="base",output='JSON',callback=None):
    url = "https://restapi.amap.com/v3/config/district?parameters"
    params = {
        "key":key,
        "keywords":keywords,
        "subdistrict":subdistrict,
        "page":page,
        "offset":offset,
        "extensions":extensions,
        "output":output,
        "callback":callback  
    }
    response = requests.get(url,params=params)
    results = pd.json_normalize(response.json()['districts'][0]['districts'])
    return results


# In[30]:


administration_keywords = "广东"


# In[31]:


administration(lv_key,administration_keywords)


# ### 搜索POI
# #### 关键字搜索
# > * 1. 具体应用场景：用户可以通过指定区域和指定关键字，搜索到相关的地点的基本信息（图片、位置等）
# > * 2.url:https://restapi.amap.com/v3/place/text?parameters
# > * 3.参数：
# >> * 3.1必选参数：key,keywords,types

# In[33]:


"""关键字搜索函数"""
"""keywords为搜索内容的关键字，city为搜索内容所在城市"""
def text(key,keywords,city,types=None,citylimit="true",extensions="all",children=0,offset=20,page=1,output='JSON',callback=None):
    url = "https://restapi.amap.com/v3/place/text?parameters"
    params = {
        "key":key,
        "keywords":keywords,
        "types":types,
        "city":city,
        "citylimit":citylimit,
        "extensions":extensions,
        "children":children,
        "offset":offset,
        "page":page,
        "output":output,
        "callback":callback 
    }
    response = requests.get(url,params=params)
    result = response.json()
    return result


# In[34]:


text_keywords = "旅游景区"
text_city = "广东"


# In[35]:


text(lv_key,text_keywords,text_city)


# #### 周边搜索
# > * 1. 具体应用场景：用户可以通过关键字和指定中心地点，展开搜索四周的相关内容
# > * 2. 周边搜索URL：https://restapi.amap.com/v3/place/around?parameters   
# > * 3. 请求方式：request.get   
# > * 4. 必填参数：key,location 

# In[36]:


"""周边搜索函数"""
"""location为中心点坐标，keywords为搜索内容关键字"""
def around(key,location,keywords,city=None,radius=3000,sortrule="distance",offset=20,page=1,extensions="base",output='JSON',callback=None):
    url = "https://restapi.amap.com/v3/place/around?parameters"
    params = {
        "key":key,
        "location":location,
        "keywords":keywords,
        "city":city,
        "radius":radius,
        "sortrule":sortrule,
        "offset":offset,
        "page":page,
        "extensions":extensions,
        "output":output,
        "callback":callback 
    }
    response = requests.get(url,params=params)
    result = response.json()
    #result = pd.json_normalize(response.json()['pois'][0]['type'])
    return result


# In[37]:


around_location = origin_中大南方
around_keywords = "美食"


# In[38]:


around(lv_key,around_location,around_keywords)


# #### 多边形搜索
# > * 1. 多边形搜索URL：https://restapi.amap.com/v3/place/polygon?parameters   
# > * 3. 请求方式：request.get   
# > * 3. 必填参数：key,polygon(经纬度)

# In[40]:


def poly(key,polygon,keywords=None,types=None,offset='20',page='1',extensions='base',sig=None,output='json',callback=None):
    #多边形搜索
    url='https://restapi.amap.com/v3/place/polygon?parameters '
    params={
        'key':key,
        'polygon':polygon,
        'keywords':keywords,
        'types':types,
        'offset':offset,
        'page':page,
        'extensions':extensions,
        'sig':sig,
        'output':output,
        'callback':callback     
    }
    response=requests.get(url,params)
    results=response.json()
    # return
    return results


# In[41]:


polygon='116.460988,40.006919|116.48231,40.007381;116.47516,39.99713|116.472596,39.985227|116.45669,39.984989|116.460988,40.006919'
poly(lv_key,polygon,keywords=None,types=None,offset='20',page='1',extensions='base',sig=None,output='json',callback=None)


# #### ID查询
# > * 1. 具体应用场景：用户通过兴趣点的唯一标识ID查询到此地点的基本信息（照片、地址等）
# > * 1. URL：https://restapi.amap.com/v3/place/detail?parameters   
# > * 3. 请求方式：request.get   
# > * 3. 必填参数：key,id(兴趣点ID)

# In[43]:


"""ID查询函数"""
"""id为兴趣点的唯一标识ID"""
def id_search(key,id,output='JSON',callback=None):
    url = "https://restapi.amap.com/v3/place/detail?parameters "
    params = {
        "key":key,
        "id":id,
        "output":output,
        "callback":callback 
    }
    response = requests.get(url,params=params)
    result = response.json()
    return result


# In[44]:


id_search(lv_key,'B0G3AYBO5X')


# ### IP定位
# > * 1. 具体应用场景：通过IP搜索到此IP的相关信息
# > * 2. URL：https://restapi.amap.com/v3/ip?parameters   
# > * 3. 请求方式：request.get   
# > * 4. 必填参数：key,ip(可选)

# In[46]:


"""IP定位函数"""
def ip_locating(key,ip,output='JSON'):
    url = "https://restapi.amap.com/v3/ip?parameters"
    params = {
        "key":key,
        "ip":ip,
        "output":output
    }
    response = requests.get(url,params=params)
    result = response.json()
    return result


# In[47]:


ip_locating(lv_key,"182.254.192.28")


# ### 静态地图
# > * 1. 具体应用场景：为用户返回指定地点的地图，地图中包括周边路况、基础设施。
# > * 2. URL：https://restapi.amap.com/v3/staticmap?parameters   
# > * 3. 请求方式：request.get   
# > * 4. 必填参数：key，location，zoom

# In[49]:


"""获取静态地图函数"""
"""location为中心点坐标，zoom为地图缩放级别:[1,17]"""
def staticmap(key,location,zoom,size="600*300",scale=2,markers=None,labels=None,paths=None,traffic=1):
    #zoom=None,size=400*400,scale=2,markers=None,labels=None,paths=None,traffic=1
    url = "https://restapi.amap.com/v3/staticmap?parameters"
    params = {
        "key":key,
        "location":location,
        "zoom":zoom,
        "size":size,
        "scale":scale,
        "markers":markers,
        "labels":labels,
        "paths":paths,
        "traffic":traffic
    }
    r = requests.get(url,params=params)
    result = r.content
    results = Image.open(BytesIO(r.content))
    return results


# In[50]:


staticmap_location = origin_中大南方


# In[62]:


staticmap(lv_key,staticmap_location,17)


# ### 坐标转换
# > * 1. 能够将用户输入的非高德坐标（GPS坐标、mapbar坐标、baidu坐标）转换成高德坐标.
# > * 2. URL：https://restapi.amap.com/v3/assistant/coordinate/convert?parameters
# > * 3. 请求方式：request.get   
# > * 4. 必填参数：key，locations(坐标点)

# In[53]:


"""坐标转换函数"""
"""location为所需转换的地址的坐标"""
def coordinate_convert(key,locations,coordsys="autonavi",output='JSON'):
    url = "https://restapi.amap.com/v3/assistant/coordinate/convert?parameters"
    params = {
        "key":key,
        "locations":locations,
        "coordsys":coordsys,
        "output":output
    }
    response = requests.get(url,params=params)
    result = response.json()
    return result


# In[54]:


coordinate_convert(lv_key,origin_中大南方)


# ### 天气查询
# > * 1. 具体应用场景：为用户返回指定地点的当前天气状况或预测天气状况。
# > * 2. URL：https://restapi.amap.com/v3/weather/weatherInfo?parameters
# > * 3. 请求方式：request.get   
# > * 4. 必填参数：key，city

# In[56]:


"""查询天气函数"""
"""city为所需查询的城市的城市编码"""
def weather(key,city,extensions="base",output='JSON'):
    url = "https://restapi.amap.com/v3/weather/weatherInfo?parameters"
    params = {
        "key":key,
        "city":city,
        "extensions":extensions,
        "output":output
    }
    response = requests.get(url,params=params)
    result = pd.json_normalize(response.json()['lives'])
    return result


# In[59]:


weather(lv_key,"440100")


# ### 输入提示
# > * 1. 具体应用场景：为用户搜索与关键词相关的地点。
# > * 2. URL：https://restapi.amap.com/v3/assistant/inputtips?parameters
# > * 3. 请求方式：request.get   
# > * 4. 必填参数：key，keywords(查询关键词)

# In[60]:


"""获取输入提示函数"""
"""keywords为搜索关键字，city为所需查询的城市的城市编码"""
def inputtips(key,keywords,city,type=None,location=None,citylimit="true",datatype="all",output='JSON',callback=None):
    url = "https://restapi.amap.com/v3/assistant/inputtips?parameters"
    params = {
        "key":key,
        "keywords":keywords,
        "city":city,
        "type":type,
        "location":location,
        "citylimit":citylimit,
        "datatype":datatype,
        "output":output,
        "callback":callback
    }
    response = requests.get(url,params=params)
    result = pd.json_normalize(response.json()['tips'])
    return result


# In[61]:


inputtips(lv_key,"奶茶店","440100")


# In[ ]:




